﻿// Part of this class has been taken from Droid Explorer <http://de.codeplex.com/license>
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using DroidManager.Data;

namespace DroidManager.Android.Aapt
{
    internal enum AaptCommand
    {
        Dump_Badging,
        Dump_Permissions,
        Dump_Resources,
        Dump_Configuration,
        Dump_XmlTree,
        Dump_XmlStrings,
        List,
        Package,
        Remove,
        Add,
        Version,
    }

    /// <summary>
    /// Used to load Apk Info
    /// </summary>
    public class AaptHandler
    {
        private static AaptHandler _instance;

        internal AaptHandler()
        {
            _instance = this;
        }

        /// <summary>
        /// AaptHandler's Instance
        /// </summary>
        public static AaptHandler Instance
        {
            get
            {
                if (_instance == null)
                {
                    _instance = new AaptHandler();
                }
                return _instance;
            }
        }

        private CommandResult AaptCommandRun(AaptCommand command, string args)
        {
            switch (command)
            {
                case AaptCommand.Dump_Badging:
                    return new AaptBrandingCommandResult(RunAaptCommand(command, args));
                case AaptCommand.Dump_Permissions:
                    return new AaptPermissionsCommandResult(RunAaptCommand(command, args));
                default:
                    return null;
            }
        }

        private string RunAaptCommand(AaptCommand command, string args)
        {
            //string localPath = System.IO.Path.GetDirectoryName ( typeof ( CommandRunner ).Assembly.Location );

            StringBuilder result = new StringBuilder();
            Process proc = new Process();
            StringBuilder commandArg = new StringBuilder(AaptCommandToString(command));
            if (!string.IsNullOrEmpty(args))
            {
                commandArg.AppendFormat(" {0}", args);
            }
            ProcessStartInfo psi = new ProcessStartInfo(GlobalVars.AaptFilePath, commandArg.ToString());

            psi.CreateNoWindow = true;
            psi.ErrorDialog = true;
            psi.UseShellExecute = false;
            psi.RedirectStandardOutput = true;
            psi.RedirectStandardError = true;
            psi.WindowStyle = ProcessWindowStyle.Hidden;
            proc.StartInfo = psi;
            proc.OutputDataReceived += delegate(object sender, DataReceivedEventArgs e)
                                           {
                                               if (!string.IsNullOrEmpty(e.Data))
                                               {
                                                   result.AppendLine(e.Data.Trim());
                                               }
                                           };

            proc.ErrorDataReceived += delegate(object sender, DataReceivedEventArgs e)
                                          {
                                              if (!string.IsNullOrEmpty(e.Data))
                                              {
                                                  result.AppendLine(e.Data.Trim());
                                              }
                                          };

            proc.Exited += delegate(object sender, EventArgs e)
                               {
                                   //NOTE Aapt event handler
                               };
            proc.Start();
            proc.BeginOutputReadLine();
            proc.BeginErrorReadLine();
            proc.WaitForExit();
            return result.ToString();
        }

        private string AaptCommandToString(AaptCommand command)
        {
            return command.ToString().Replace("_", " ").ToLower();
        }

        /// <summary>
        /// Loads Application info from apk file
        /// </summary>
        /// <param name="apkFile">APK File path</param>
        /// <returns></returns>
        public AaptBrandingCommandResult GetLocalApkInformation(string apkFile)
        {
            if (string.IsNullOrEmpty(apkFile) || !System.IO.File.Exists(apkFile))
            {
                throw new System.IO.FileNotFoundException("File was not found on device.",
                                                          System.IO.Path.GetFileName(apkFile));
            }

            AaptBrandingCommandResult result =
                AaptCommandRun(AaptCommand.Dump_Badging, string.Format("\"{0}\"", apkFile)) as AaptBrandingCommandResult;
            result.LocalApk = apkFile;
            return result;
        }

        /// <summary>
        /// Loads Application Permissions from apk file
        /// </summary>
        /// <param name="apkFile">APK File Path</param>
        /// <returns></returns>
        public List<string> GetLocalApkPermissions(string apkFile)
        {
            System.IO.FileInfo lApk = new System.IO.FileInfo(apkFile);
            if (lApk == null || !lApk.Exists)
            {
                throw new System.IO.FileNotFoundException("File was not found on device.", apkFile);
            }

            AaptPermissionsCommandResult result =
                AaptCommandRun(AaptCommand.Dump_Permissions, string.Format("\"{0}\"", apkFile)) as
                AaptPermissionsCommandResult;

            if (result != null)
            {
                return result.Permissions;
            }
            else
            {
                return null;
            }
        }
    }
}